package com.ledou44.blokus.controller;

import com.alibaba.fastjson.JSON;
import com.ledou44.blokus.service.WebSocketServiceHelper;
import com.ledou44.blokus.vo.Message;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author ledou44
 * 处理websocket连接请求的controller
 */
@ServerEndpoint("/connection")
@Component
public class WebSocketService {
    /**
     * 临时存放客户端
     */
    private static final Map<String, Session> soonClients = new ConcurrentHashMap<>();
    /**
     * 存放用户id对应哪个游戏，即gameClients的key
     */
    private static final Map<String, String> userGame = new ConcurrentHashMap<>();
    /**
     * 存放所有对局的详情客户端
     */
    private static final Map<String, Set<Session>> gameClients = new ConcurrentHashMap<>();
    /**
     * 当前已经产生的游戏局数
     */
    private static final AtomicInteger gameNum = new AtomicInteger(0);
    /**
     * 工具类
     */
    private static final WebSocketServiceHelper webSocketServiceHelper = new WebSocketServiceHelper();

    @OnOpen
    public void onOpen(Session session) {
        if(soonClients.size() < 4) {
            soonClients.put(session.getId(),session);
        }
        if(soonClients.size() == 4) {
            Map<String,Object> message = new HashMap<>();
            message.put("gameState","start");
            String gameKey = "game" + gameNum;
            message.put("gameKey", gameKey);
            gameNum.incrementAndGet();
            webSocketServiceHelper.sendAllMessageWithChessColor(message, soonClients);
            Set<Session> sessions = new HashSet<>(soonClients.values());
            for(Session sess : sessions) {
                userGame.put(sess.getId(),gameKey);
            }
            gameClients.put(gameKey, sessions);
            soonClients.clear();
        }
    }

    @OnClose
    public void onClose(Session session) {
        String sessionId = session.getId();
        String gameKey = userGame.get(sessionId);
        if(gameKey != null) {
            Map<String,Object> message = new HashMap<>();
            message.put("gameState","error");
            for(Session sess : gameClients.get(gameKey)) {
                userGame.remove(sess.getId());
                if(sess.getId().equals(sessionId)) {
                    continue;
                }
                webSocketServiceHelper.sendMessage(sess,message);
                try {
                    sess.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            gameClients.remove(gameKey);
        }
        soonClients.remove(sessionId);
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        throwable.printStackTrace();
        this.onClose(session);
    }

    @OnMessage
    public void onMessage(String msg, Session session) {
        Message message = JSON.parseObject(msg, Message.class);
        if(message.getGameState().equals("running") || message.getGameState().equals("pass")) {
            webSocketServiceHelper.sendMessageExcept(session.getId(), message, gameClients.get(message.getGameKey()));
        } else if(message.getGameState().equals("error")) {
            System.out.println(new Date() + message.getErrorMessage());
        }
    }
}
